using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Text;
using Forecast.Database;

namespace Forecast.Business
{
    public class ActivePredictions
    {
        #region Enums

        public enum Columns
        {
            None,
            PredictionId,
            Ticker,
            Prediction,
            EndDate,
            ActivityLevel,
            RequestedAt,
            OfferedAt,
            Value,
            LastChange,
            AllTrades
        }

        #endregion  
        #region Interface

        internal DataTable GetActivePredictions(IList<Prediction> allActivePredictions, IList<Offer> allOffers)
        {
            DataTable table = GetEmptyDataTableForActivePredictions();

            foreach (Prediction prediction in allActivePredictions)
            {
                DataRow row = table.NewRow();

                row[Columns.PredictionId.ToString()] = prediction.Id;
                row[Columns.Ticker.ToString()] = prediction.Ticker;
                row[Columns.Prediction.ToString()] = prediction.ShortDescription;
                row[Columns.EndDate.ToString()] = prediction.EndDate;
                row[Columns.ActivityLevel.ToString()] = GetActivityLevel(prediction, allOffers);
                row[Columns.RequestedAt.ToString()] = GetRequestedAt(prediction, allOffers);
                row[Columns.OfferedAt.ToString()] = GetOfferedAt(prediction, allOffers);
                row[Columns.Value.ToString()] = prediction.LastValue;
                row[Columns.LastChange.ToString()] = prediction.LastChange;
                row[Columns.AllTrades.ToString()] = GetAllTrades(prediction, allOffers);

                table.Rows.Add(row);
            }

            return table;
        }

        #endregion
        #region Helper methods

        private int GetActivityLevel(Prediction prediction, IList<Offer> allOffers)
        {
            int activityLevel = 0;

            foreach (Offer offer in allOffers)
            {
                if (offer.PredictionId == prediction.Id)
                    activityLevel++;
            }

            return activityLevel;
        }

        internal static int[] GetAllTrades(Prediction prediction, IList<Offer> allOffers)
        {
            IList<Offer> offersInPrediction = GetAcceptedOffersInPrediction(prediction, allOffers);
            if (offersInPrediction.Count == 0)
                return new int[0];

            int[] allTrades = new int[offersInPrediction.Count];
            int index = 0;
            foreach (Offer offer in offersInPrediction)
            {
                allTrades[index] = offer.Price;
                index++;
            }
            return allTrades;
        }

        private static IList<Offer> GetAcceptedOffersInPrediction(Prediction prediction, IList<Offer> allOffers)
        {
            IList<Offer> offersInPrediction = new List<Offer>();
            foreach (Offer offer in allOffers)
            {
                if (offer.PredictionId != prediction.Id)
                    continue;
                if (offer.IsAccepted)
                    offersInPrediction.Add(offer); // HACK; ordered in sql (order by [End_date] ASC)
            }
            return offersInPrediction;
        }

        private int GetRequestedAt(Prediction prediction, IList<Offer> allOffers)
        {
            int requestedAt = 0;

            foreach (Offer offer in allOffers)
            {
                if (offer.PredictionId != prediction.Id)
                    continue;
                if (offer.IsAccepted)
                    continue;
                if (!offer.IsActive)
                    continue;
                if (!offer.IsBuy)
                    continue;
                if (offer.Price > requestedAt)
                    requestedAt = offer.Price;
            }

            return requestedAt;
        }

        private int GetOfferedAt(Prediction prediction, IList<Offer> allOffers)
        {
            int offeredAt = 100;

            foreach (Offer offer in allOffers)
            {
                if (offer.PredictionId != prediction.Id)
                    continue;
                if (offer.IsAccepted)
                    continue;
                if (!offer.IsActive)
                    continue;
                if (offer.IsBuy)
                    continue;
                if (offer.Price < offeredAt)
                    offeredAt = offer.Price;
            }

            return offeredAt;
        }

        private DataTable GetEmptyDataTableForActivePredictions()
        {
            DataTable dataTable = new DataTable("ActivePredictions");

            DataColumn columnPredictionId = new DataColumn();
            columnPredictionId.ColumnName = Columns.PredictionId.ToString();
            columnPredictionId.DataType = typeof(int);
            dataTable.Columns.Add(columnPredictionId);

            DataColumn columnTicker = new DataColumn();
            columnTicker.ColumnName = Columns.Ticker.ToString();
            columnTicker.DataType = typeof(string);
            dataTable.Columns.Add(columnTicker);

            DataColumn columnPrediction = new DataColumn();
            columnPrediction.ColumnName = Columns.Prediction.ToString();
            columnPrediction.DataType = typeof(string);
            dataTable.Columns.Add(columnPrediction);

            DataColumn columnEndDate = new DataColumn();
            columnEndDate.ColumnName = Columns.EndDate.ToString();
            columnEndDate.DataType = typeof(DateTime);
            dataTable.Columns.Add(columnEndDate);

            DataColumn columnValue = new DataColumn();
            columnValue.ColumnName = Columns.Value.ToString();
            columnValue.DataType = typeof(int);
            dataTable.Columns.Add(columnValue);

            DataColumn columnActivityLevel = new DataColumn();
            columnActivityLevel.ColumnName = Columns.ActivityLevel.ToString();
            columnActivityLevel.DataType = typeof(int);
            dataTable.Columns.Add(columnActivityLevel);

            DataColumn columnRequestedAt = new DataColumn();
            columnRequestedAt.ColumnName = Columns.RequestedAt.ToString();
            columnRequestedAt.DataType = typeof(int);
            dataTable.Columns.Add(columnRequestedAt);

            DataColumn columnOfferedAt = new DataColumn();
            columnOfferedAt.ColumnName = Columns.OfferedAt.ToString();
            columnOfferedAt.DataType = typeof(int);
            dataTable.Columns.Add(columnOfferedAt);

            DataColumn columnLastChange = new DataColumn();
            columnLastChange.ColumnName = Columns.LastChange.ToString();
            columnLastChange.DataType = typeof(double);
            dataTable.Columns.Add(columnLastChange);

            DataColumn columnAllTrades = new DataColumn();
            columnAllTrades.ColumnName = Columns.AllTrades.ToString();
            columnAllTrades.DataType = typeof(int[]);
            dataTable.Columns.Add(columnAllTrades);

            return dataTable;
        }

        #endregion
    }
}
